package com.github.slprj.slake.net;

import com.github.slprj.slake.pb.PbUtil;

import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;

/**
 * @author YangXiaoLong
 * 2022/9/11 21:46
 */
public abstract class WriteFrame extends Frame {

    //存储空间大小
    private int dumpSize;

    /**
     * body的大小
     */
    protected abstract int bodySize();

    protected abstract void encodeBody(ByteBuffer buf);

    public int estimateSize() {
        if (dumpSize == 0) {
            //msg存在汉字,一个汉字占3个字节
            int msgBytes = msg == null ? 0 : msg.length() * 3 + (1 + 5);
            //4:表示整个长度
            dumpSize = 4
                    + (1 + 5) * 4
                    + msgBytes
                    + bodySize() + (1 + 5);
        }
        return dumpSize;
    }

    public void encode(ByteBuffer buf) {
        int startPos = buf.position();
        buf.position(startPos + 4);
        if (frameType != 0) {
            PbUtil.writeTag(buf, PbUtil.TYPE_VAR_INT, Frame.IDX_TYPE);
            PbUtil.writeVarUnsignedInt32(buf, frameType);
        }
        if (command != 0) {
            PbUtil.writeTag(buf, PbUtil.TYPE_VAR_INT, Frame.IDX_COMMAND);
            PbUtil.writeVarUnsignedInt32(buf, command);
        }
        if (seq != 0) {
            PbUtil.writeTag(buf, PbUtil.TYPE_VAR_INT, Frame.IDX_SEQ);
            PbUtil.writeVarUnsignedInt32(buf, seq);
        }
        if (respCode != 0) {
            PbUtil.writeTag(buf, PbUtil.TYPE_VAR_INT, Frame.IDX_RESP_CODE);
            PbUtil.writeVarUnsignedInt32(buf, respCode);
        }
        if (msg != null && msg.length() > 0) {
            PbUtil.writeTag(buf, PbUtil.TYPE_LENGTH_DELIMITED, Frame.IDX_MSG);
            byte[] bs = msg.getBytes(StandardCharsets.UTF_8);
            PbUtil.writeVarUnsignedInt32(buf, bs.length);
            buf.put(bs);
        }
        encodeBody(buf);
        buf.putInt(startPos, buf.position() - startPos - 4);
    }
}
